package opengles;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.os.Environment;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import Camera.CameraEngine;

/**
 * Created by freehyan on 9/7/2016.
 */
public class GLESRenderer extends GLSurfaceView implements GLSurfaceView.Renderer{
    private CameraEngine mCamera;
    private SurfaceTexture mSurface;
    private FBO mFBO;
    private int[] mFBOColorTex0;

    private CameraFBOPass mCameraPass;
    private PrimaryPass mPrimaryPass;
    private Context mActivityContext;

    private final int mFBOWidth = 1080;
    private final int mFBOHeight = 1845;
    private int mPhoneWidth;
    private int mPhoneHeight;
    private int mCameraTexture;

    public GLESRenderer(Context context, CameraEngine camera)
    {
        super(context);
        mActivityContext = context;
        mCamera = camera;
        setEGLContextClientVersion(2);
        setRenderer(this);
    }

    static int t = 0;
    @Override
    public void onDrawFrame(GL10 gl) {
 //       float[] mtx = new float[16];
        mSurface.updateTexImage();
//      mSurface.getTransformMatrix(mtx);

        mFBO.openFBO();
        GLES20.glViewport(0, 0, mFBOWidth, mFBOHeight);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        mCameraPass.render();

        t++;
        if (t== 10)
        {
           // GLES30.glPixelStorei(GLES30.GL_PACK_ALIGNMENT,1);
            int width = mFBOWidth, height = mFBOHeight;
            ByteBuffer PixelsBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder());
            long start = System.currentTimeMillis();
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFBOColorTex0[0]);
            Log.e("GLES", "before glReadPixels: " + (System.currentTimeMillis() - start));
            GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, PixelsBuffer);
            Log.e("GLES", "after glReadPixels: " + (System.currentTimeMillis() - start));
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
           saveRgb2Bitmap(PixelsBuffer, "GLES", width, height);
        }
        mFBO.closeFBO();

        drawScreenQuad();

//        float[] mtx = new float[16];
//        mSurface.updateTexImage();
//        mSurface.getTransformMatrix(mtx);
//        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
          //mCameraPass.copyTextureToScreen();
    }

    private void drawScreenQuad(){
        GLES20.glViewport(0, 0, mPhoneWidth, mPhoneHeight);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        mFBO.bindForReadTargetTex(GLES20.GL_TEXTURE0, mFBOColorTex0[0]);
        mPrimaryPass.render();
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        mPhoneWidth = width;
        mPhoneHeight = height;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        //int texture = Texture.createTexture(mFBOWidth, mFBOHeight);
        mCameraTexture = Texture.createCameraTexture();
        mCameraPass = new CameraFBOPass(mCameraTexture, mActivityContext);
        mSurface = new SurfaceTexture(mCameraTexture);
        mCamera.startCamera(mSurface);

        mFBO = new FBO();
        mFBOColorTex0 = new int[1];
        mFBO.initFBO(mFBOWidth, mFBOHeight);
        //mFBO.mountTexture(mFBOColorTex0, 0);
        mFBOColorTex0[0] = mCameraTexture;
        mFBO.mountTexture(mFBOColorTex0, 0);
        mFBO.attachTex2FBO();

//        int ImageId = Texture.loadImageFromFile(mActivityContext.getResources(), R.drawable.p_300px);
        mCameraPass = new CameraFBOPass(mCameraTexture, mActivityContext);

        mPrimaryPass = new PrimaryPass(mFBOColorTex0[0], mActivityContext);
    }

    static void saveRgb2Bitmap(Buffer buf, String filename, int width, int height) {
        Log.d("GLES", "Creating " + filename);
        File extDir = Environment.getExternalStoragePublicDirectory("Pictures");
        File fullFilename = new File(extDir, filename + ".png");

        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(fullFilename));
            Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            bmp.copyPixelsFromBuffer(buf);

//            Matrix matrix = new Matrix();
//            matrix.setScale(-1, 1);
//            matrix.preRotate(180);
//            Bitmap rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
//            rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 90, bos);

            bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
            bmp.recycle();
            //rotatedBitmap.recycle();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
